/*!
 * SPDX-License-Identifier: Apache-2.0
 *
 * The OpenSearch Contributors require contributions made to
 * this file be licensed under the Apache-2.0 license or a
 * compatible open source license.
 *
 * Modifications Copyright OpenSearch Contributors. See
 * GitHub history for details.
 */

.ouiSwitch {
  position: relative;
  display: inline-flex;
  align-items: flex-start;
  min-height: $ouiSwitchHeight;

  .ouiSwitch__label {
    cursor: pointer;
    padding-left: $ouiSizeS;
    line-height: $ouiSwitchHeight;
    font-size: $ouiFontSizeS;
    vertical-align: middle;
    display: inline-block;
  }

  .ouiSwitch__button {
    flex-shrink: 0; // ensures the button doesn't lose width because of a long label
    line-height: 0; // ensures button takes height of switch inside

    &:focus .ouiSwitch__track {
      @include ouiCustomControlFocused;
    }

    &:disabled {
      &:hover,
      ~ .ouiSwitch__label:hover {
        cursor: not-allowed;
      }

      .ouiSwitch__body {
        background-color: $ouiSwitchOffColor;
      }

      .ouiSwitch__thumb {
        @include ouiCustomControlDisabled;
        background-color: $ouiSwitchOffColor;
      }

      .ouiSwitch__icon {
        fill: $ouiFormCustomControlDisabledIconColor;
      }

      + .ouiSwitch__label {
        color: $ouiFormControlDisabledColor;
      }
    }

    &[aria-checked='false'] {
      .ouiSwitch__body {
        background-color: $ouiSwitchOffColor;
      }

      // When input is not checked, we shift around the positioning of the thumb and the icon
      .ouiSwitch__thumb { // move the thumb left
        left: 0;
      }

      .ouiSwitch__icon { // move the icon right
        right: -$ouiSizeS;

        &.ouiSwitch__icon--checked {
          right: auto;
          left: -($ouiSwitchWidth - calc($ouiSwitchThumbSize / 2));
        }
      }
    }
  }

  .ouiSwitch__body {
    pointer-events: none;
    width: $ouiSwitchWidth;
    height: $ouiSwitchHeight;
    display: inline-block;
    position: relative;
    border-radius: $ouiSwitchHeight;
    vertical-align: middle;
  }

  .ouiSwitch__thumb {
    @include ouiCustomControl($type: 'round', $size: $ouiSwitchThumbSize);

    position: absolute;
    display: inline-block;
    left: $ouiSwitchWidth - $ouiSwitchThumbSize;
    transition: border-color $ouiAnimSpeedNormal $ouiAnimSlightBounce, background-color $ouiAnimSpeedNormal $ouiAnimSlightBounce, left $ouiAnimSpeedNormal $ouiAnimSlightBounce, transform $ouiAnimSpeedNormal $ouiAnimSlightBounce;
  }

  .ouiSwitch__track {
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    overflow: hidden;
    border-radius: $ouiSwitchHeight;
  }

  .ouiSwitch__icon {
    position: absolute;
    right: -($ouiSwitchWidth - calc($ouiSwitchThumbSize / 2));
    top: calc(($ouiSwitchHeight - $ouiSwitchIconHeight) / 2);
    bottom: 0;
    width: $ouiSwitchWidth - calc($ouiSwitchThumbSize / 2) + $ouiSizeS;
    height: $ouiSwitchIconHeight;
    transition: left $ouiAnimSpeedNormal $ouiAnimSlightBounce, right $ouiAnimSpeedNormal $ouiAnimSlightBounce;
    fill: $ouiTextColor;
  }

  .ouiSwitch__icon--checked {
    right: auto;
    left: -$ouiSizeS;
    fill: $ouiColorEmptyShade;
  }

  &:hover .ouiSwitch__button {
    &:not(:disabled) .ouiSwitch__thumb {
      transform: scale(1.05);
    }

    &:active .ouiSwitch__thumb {
      transform: scale(.95);
    }
  }

  // Compressed switches operate very similar to the normal versions, but are smaller, contain no icon signifiers
  &.ouiSwitch--compressed {
    min-height: $ouiSwitchHeightCompressed;

    .ouiSwitch__label {
      line-height: $ouiSwitchHeightCompressed;
    }

    .ouiSwitch__body {
      width: $ouiSwitchWidthCompressed;
      height: $ouiSwitchHeightCompressed;
      border-radius: $ouiSwitchHeightCompressed;
    }

    .ouiSwitch__thumb {
      @include ouiCustomControl($type: 'round', $size: ($ouiSwitchThumbSizeCompressed) - 2px);

      left: ($ouiSwitchWidthCompressed) - (($ouiSwitchThumbSizeCompressed) - 2px) - 1px;
      top: 1px;
      transition: border-color $ouiAnimSpeedNormal $ouiAnimSlightBounce, background-color $ouiAnimSpeedNormal $ouiAnimSlightBounce, left $ouiAnimSpeedNormal $ouiAnimSlightBounce, transform $ouiAnimSpeedNormal $ouiAnimSlightBounce;
    }

    .ouiSwitch__track {
      border-radius: $ouiSwitchHeightCompressed;
    }
  }

  // Mini styling is similar to compressed, but even smaller. It's undocumented because it has very specific uses.
  &.ouiSwitch--mini {
    min-height: $ouiSwitchHeightMini;

    .ouiSwitch__label {
      line-height: $ouiSwitchHeightMini;
      font-size: $ouiFontSizeXS;
    }

    .ouiSwitch__body {
      width: $ouiSwitchWidthMini;
      height: $ouiSwitchHeightMini;
      border-radius: $ouiSwitchHeightMini;
    }

    .ouiSwitch__thumb {
      @include ouiCustomControl($type: 'round', $size: ($ouiSwitchThumbSizeMini) - 2px);

      left: ($ouiSwitchWidthMini) - (($ouiSwitchThumbSizeMini) - 2px) - 1px;
      top: 1px;
      transition: border-color $ouiAnimSpeedNormal $ouiAnimSlightBounce, background-color $ouiAnimSpeedNormal $ouiAnimSlightBounce, left $ouiAnimSpeedNormal $ouiAnimSlightBounce, transform $ouiAnimSpeedNormal $ouiAnimSlightBounce;
    }

    .ouiSwitch__track {
      border-radius: $ouiSwitchHeightMini;
    }
  }

  // Compressed and mini switches have some style overlap
  &.ouiSwitch--compressed,
  &.ouiSwitch--mini {

    .ouiSwitch__button[aria-checked='false'] {
      .ouiSwitch__thumb {
        left: 1px;
      }
    }

    // Compressed and mini switches need slightly darker borders since they don't have icons
    .ouiSwitch__button[aria-checked='false'],
    .ouiSwitch__button[aria-checked='true']:disabled {
      .ouiSwitch__thumb {
        border-color: $ouiFormCustomControlBorderColor;
      }
    }

    // Similar additional treatment needed while checked
    .ouiSwitch__button[aria-checked='true'] {
      .ouiSwitch__thumb {
        border-color: $ouiColorPrimary;
      }
    }
  }

  &.ouiSwitch--base {
    border: solid 1px transparent;
    cursor: pointer;
    height: $ouiButtonHeight;
    line-height: $ouiButtonHeight;
    vertical-align: middle;
    align-items: stretch;
    border-radius: $ouiBorderRadius;
    padding: 0 $ouiSize - $ouiSizeXS;

    .ouiSwitch__label {
      // sass-lint:disable-block no-important
      line-height: $ouiFormControlLayoutGroupInputHeight !important;
    }

    &.ouiSwitch--compressed,
    &.ouiSwitch--mini {
      height: $ouiButtonHeightSmall;
      line-height: $ouiButtonHeightSmall;

      .ouiSwitch__label {
        // sass-lint:disable-block no-important
        line-height: $ouiFormControlLayoutGroupInputCompressedHeight !important;
      }
    }

    &.ouiSwitch-isDisabled {
      border-color: $ouiButtonColorDisabled;
      cursor: not-allowed;

      &:hover,
      &:focus,
      &:focus-within {
        @include ouiSlightShadow;
      }
    }
  }
}

// sass-lint:disable-block nesting-depth
@each $name, $color in $ouiSwitchColors {
  .ouiSwitch--#{$name} {
    &.ouiSwitch--base {
      @include ouiUseDefaultButtonShadows {
        @include ouiSlightShadow;
      }
      @include ouiButtonFocus;

      border-color: $color;

      @if ($name == 'ghost') {
        // Ghost is unique and ALWAYS sits against a dark background.
        color: $color;
      } @else if ($name == 'text') {
        // The default color is lighter than the normal text color, make the it the text color
        color: $ouiTextColor;
      } @else {
        // Other colors need to check their contrast against the page background color.
        color: makeHighContrastColor($color, $ouiPageBackgroundColor);
      }

      &:not([class*='isDisabled']) {
        $shadowColor: $ouiShadowColor;
        @if ($name == 'ghost') {
          $shadowColor: $ouiColorInk;
        } @else if (lightness($ouiTextColor) < 50) {
          // Only if this is the light theme do we use the button variant color to colorize the shadow
          $shadowColor: desaturate($color, 60%);
        }

        @include ouiUseDefaultButtonShadows {
          @include ouiSlightShadow($shadowColor);
        }

        &:hover,
        &:focus,
        &:focus-within {
          @include ouiSlightShadowHover($shadowColor);
          background-color: transparentize($color, .9);
        }

        &:active {
          @include ouiSlightShadowActive($color);
        }
      }
    }

    .ouiSwitch__body {
      background-color: $color;
    }

    &.ouiSwitch--compressed,
    &.ouiSwitch--mini {
      .ouiSwitch__button[aria-checked='true'] {
        .ouiSwitch__thumb {
          border-color: $color;
        }
      }
    }
  }
}
